package com.simga.library.http;

import android.util.SparseArray;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;

public class Request implements IRequestResult, Event {

    private SparseArray<List<Observable>> observables;

    public Request() {
        observables = new SparseArray<>(0);
    }

    public <T> void request(final int postCode, final Observable<T> request, final Object data, final int event) {
        addObservable(event, request);
        request.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(final Disposable disposable) throws Exception {
                        doOnSubscribe(postCode, data, disposable);

                    }
                }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Object>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(final Object t) {
                        removeObservable(event, request);
                        Request.this.onNext(postCode, t, data);
                    }

                    @Override
                    public void onError(final Throwable e) {
                        removeObservable(event, request);
                        Request.this.onError(postCode, data, e);
                    }

                    @Override
                    public void onComplete() {
                        removeObservable(event, request);
                        Request.this.onCompleted(postCode, data);
                    }
                });
    }

    private void addObservable(int event, Observable request) {
        List<Observable> observables = this.observables.get(event);
        if (observables == null) {
            observables = new ArrayList<>(0);
            this.observables.put(event, observables);
        }
        observables.add(request);
    }

    private void removeObservable(int event, Observable request) {
        List<Observable> observables = this.observables.get(event);
        if (observables != null)
            observables.remove(request);
    }

    public void onCreated() {
        remove(CREATE);
    }

    public void onStart() {
        remove(START);
    }

    public void onResume() {
        remove(RESUME);
    }

    public void onPause() {
        remove(PAUSE);
    }

    public void onStop() {
        remove(STOP);
    }

    public void onDestroy() {
        remove(DESTROY);
    }

    private void remove(int event) {
        List<Observable> observables = this.observables.get(event);
        if (observables != null) {
            for (Observable ob : observables)
                if (ob != null)
                    ob.unsubscribeOn(Schedulers.io());
            observables.clear();
            this.observables.remove(event);
        }
    }

    @Override
    public void doOnSubscribe(int postCode, Object data, Disposable disposable) {

    }

    @Override
    public <T> void onNext(int postCode, T result, Object data) {

    }

    @Override
    public void onError(int postCode, Object data, Throwable e) {
        if (e instanceof HttpException) {
            //HTTP请求异常
            onHttpException(postCode, data, e);
        } else if (e instanceof IOException) {
            //网络超时
            onIOException(postCode, data, e);
        } else if (e instanceof APIException) {
            APIException exception = (APIException) e;
            if (exception.getCode().equals("1015")) {
                Request.this.onNext(postCode, null, data);
            }
            if (exception.isLoginExpired()) {
                onLoginException();
            } else {
                otherException(postCode, data, exception);
            }
        } else {
            e.printStackTrace();
        }
    }

    @Override
    public void onHttpException(int postCode, Object data, Throwable e) {

    }

    @Override
    public void onIOException(int postCode, Object data, Throwable e) {

    }

    @Override
    public void onLoginException() {

    }

    @Override
    public void onJsonParseException(int postCode, Object data, Throwable e) {

    }

    @Override
    public void onConnectException(int postCode, Object data, Throwable e) {

    }

    @Override
    public void otherException(int postCode, Object data, APIException e) {

    }

    @Override
    public void onCompleted(int postCode, Object data) {

    }
}
